package com.matrix.java.chap_06;

import java.util.Scanner;

/*
    财务应用程序：信用卡号的合法性
 */
public class Ex6_31 {
    public static void main(String[] args) {
        Scanner input = new Scanner(System.in);
        System.out.println("Enter a credit card number as a long integer:");
        long cardId = input.nextLong();
        input.close();
        if (isValid(cardId)) {
            System.out.println(cardId + " is valid");
        } else {
            System.out.println(cardId + " is invalid");
        }

    }

    private static boolean isValid(long number) {
        boolean isValid = false;
        if ((sumOfDoubleEvenPlace(number) + sumOfOddPlace(number)) % 10 == 0
                && prefixMatched(number, 4) && prefixMatched(number, 5)
                && prefixMatched(number, 37) && prefixMatched(number, 6)
                && getSize(number) > 12 && getSize(number) < 17) {
            isValid = true;
        }
        return isValid;
    }

    private static int sumOfDoubleEvenPlace(long number) {
        int size = getSize(number);
        int sum = 0;
        for (int i = 2; i <= size; i += 2) {
            sum += getPrefix(number, i) % 10;
        }
        return sum;
    }

    private static int getDigit(int number) {
        int digit;
        int size = getSize(number);
        if (size > 1) {
            digit = number / 10 + number % 10;
        } else {
            digit = number;
        }
        return digit;
    }

    private static int sumOfOddPlace(long number) {
        int size = getSize(number);
        int sum = 0;
        for (int i = 1; i < size; i += 2) {
            sum += getDigit((int) ((getPrefix(number, i) % 10) * 2));
        }
        return sum;
    }

    private static boolean prefixMatched(long number, int d) {
        return getPrefix(number, getSize(d)) == d;
    }

    private static int getSize(long d) {
        int size = 0;
        do {
            size++;
            d /= 10;
        } while (d != 0);
        return size;
    }

    private static long getPrefix(long number, int k) {
        int size = getSize(number);
        long prefix;
        if (size < k) {
            prefix = number;
        } else {
            prefix = (long) (number / Math.pow(10, size - k));
        }
        return prefix;
    }
}
